package com.atguigu.gulimall.product.utils;
//package com.jerry.test;

import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by igiroad on 2017/2/10.
 * jar版本：poi-3.7-20101029.jar, poi-ooxml-3.7-20101029.jar,
 *         poi-ooxml-schemas-3.7-20101029.jar, itextpdf-5.5.9.jar, itext-asian-5.2.0.jar
 */
public class PdfUtil {

    public static void main(String[] args) {
        String filepath = "D:\\L\\download\\办公室采购物品统计表.xls";
        String pdffilepath = doConvertPdf(filepath, "testtitle", "me", "me write", "me me", "me", true);
        doAddWaterMark(pdffilepath, "我是谁？我是谁？我是谁？我是谁？我是谁？", 38, "255, 200, 0", "200, 150", 10);
        doAddPicMark(pdffilepath, "D:\\L\\download\\123.jpg", "110, 110", "595, 842");
        System.out.println(pdffilepath);
    }

    public static String doConvertPdf(String excelFilePath, String title, String author, String subject,
                                      String keyword, String creator, boolean isA4Rotate) {
        StringBuilder sb = new StringBuilder();
        InputStream is = null;
        try {
            File excelFile = new File(excelFilePath);
            if (!excelFile.exists()) {
                return null;
            }
            String folderName = excelFile.getName().substring(0, excelFile.getName().lastIndexOf("."));
            File folderFile = new File(excelFile.getParentFile().getAbsolutePath() + File.separator + folderName);
            if (!folderFile.exists()) {
                folderFile.mkdirs();
            }
            is = new FileInputStream(excelFilePath);
            Workbook wb = WorkbookFactory.create(is);
            int sheetNum = wb.getNumberOfSheets();
            for (int m = 0; m < sheetNum; m++) {
                Sheet sheet = wb.getSheetAt(m);
                String pdfFilePath = folderFile.getAbsolutePath() + File.separator
                        + excelFile.getName() + "-" + (m + 1) + ".pdf";
                excelSheetToPdf(m, sheet, pdfFilePath, title, author, subject, keyword, creator, isA4Rotate);
                sb.append(sb.length() == 0 ? "" : ",").append(pdfFilePath);
            }
            return sb.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    private static void excelSheetToPdf(int sheetIndex, Sheet sheet, String pdfFilePath,
                                        String title, String author, String subject, String keyword,
                                        String creator, boolean isA4Rotate)
            throws IOException, DocumentException, InvalidFormatException {
        Document document = new Document();
        OutputStream os = new FileOutputStream(pdfFilePath);
        PdfWriter.getInstance(document, os);
        document.addTitle(title);//标题
        document.addAuthor(author);//作者
        document.addSubject(subject);//主题
        document.addKeywords(keyword);//关键词
        document.addCreator(creator); //创建者
        if (isA4Rotate) {
            document.setPageSize(PageSize.A4.rotate());//横向
        } else {
            document.setPageSize(PageSize.A4);//纵向
        }
        document.open();
        //开始转换并添加内容到document
        PdfPTable table = sheetToPdfTable(sheetIndex, sheet);
        document.add(table);
        //关闭文档对象
        document.close();
        os.close();
    }

    private static PdfPTable sheetToPdfTable(int sheetIndex, Sheet sheet)
            throws BadElementException, IOException {
        int rowLength = sheet.getLastRowNum() + 1;//行数
        //计算最大总列数
        int totalCNum = 0;
        for (int i = 0; i < rowLength; i++) {
            Row row = sheet.getRow(i);//当前行
            if (row == null) {
                continue;
            }
            totalCNum = row.getLastCellNum() > totalCNum ? row.getLastCellNum() : totalCNum;
        }
        System.out.println("sheetIndex=" + (sheetIndex + 1) + "  rowLength=" + rowLength + "  colLeng=" + totalCNum);
        float[] widths = new float[totalCNum];//每列宽度组合
        List<PdfPCell> cells = new ArrayList<PdfPCell>();
        //依次循环每一行，添加单元格信息
        for (int i = 0; i < rowLength; i++) {
            Row row = sheet.getRow(i);//当前行
            if (row == null) {
                for (int j = 0; j < totalCNum; j++) {
                    int rowspan = 1;
                    int colspan = 1;
                    PdfPCell pdfpCell = new PdfPCell();
                    pdfpCell.setColspan(colspan);
                    pdfpCell.setRowspan(rowspan);
                    pdfpCell.setPhrase(new Paragraph(" "));
                    cells.add(pdfpCell);
                }
                continue;
            }
//            System.out.println("totalCNum = " + totalCNum + "  row.getLastCellNum() = " + row.getLastCellNum());
            for (int j = 0; j < totalCNum; j++) {
                Cell cell = row.getCell(j);
                int rowspan = 1;
                int colspan = 1;
                if (cell == null) {
                    PdfPCell pdfpCell = new PdfPCell();
                    pdfpCell.setColspan(colspan);
                    pdfpCell.setRowspan(rowspan);
                    pdfpCell.setPhrase(new Paragraph(""));
                    cells.add(pdfpCell);
                    continue;
                }
                if (isUsed(cell, row.getRowNum(), cell.getColumnIndex())) {//该单元格被合并，则跳过
                    continue;
                }
                //读取该单元格的信息
                cell.setCellType(Cell.CELL_TYPE_STRING);
                CellRangeAddress range = getColspanRowspanByExcel(cell, row.getRowNum(), cell.getColumnIndex());
                if (range != null) {
                    rowspan = range.getLastRow() - range.getFirstRow() + 1;
                    colspan = range.getLastColumn() - range.getFirstColumn() + 1;
                } else {
                    float cw = getPOIColumnWidth(cell);
                    widths[j] = cw;
                }
                //PDF单元格
                PdfPCell pdfpCell = new PdfPCell();
                pdfpCell.setBackgroundColor(new BaseColor(getBackgroundColorByExcel(cell.getCellStyle())));
                pdfpCell.setColspan(colspan);
                pdfpCell.setRowspan(rowspan);
                pdfpCell.setVerticalAlignment(getVAlignByExcel(cell.getCellStyle().getVerticalAlignment()));//设置单元格垂直方向对其方式
                pdfpCell.setHorizontalAlignment(getHAlignByExcel(cell.getCellStyle().getAlignment()));//设置单元格水平方向对其方式
                addBorderByExcel(pdfpCell, cell);
                addFontByExcel(row, pdfpCell, cell);
//                addImageByPOICell(pdfpCell, cell, cw);
                cells.add(pdfpCell);
                j += colspan - 1;
            }
        }
        PdfPTable table = new PdfPTable(widths);
        table.setWidthPercentage(100);
        for (PdfPCell pdfpCell : cells) {
            table.addCell(pdfpCell);
        }
        return table;
    }

    /**
     * @param pdfFilePath        pdf文件地址
     * @param watermark          标识内容
     * @param fontSize           字体大小
     * @param fontRgb         rgb颜色串
     * @param position         设置起始位置 宽度、高度
     * @param angleOfinclination 倾斜角度，如30，45
     */
    private static void doAddWaterMark(String pdfFilePath, String watermark, float fontSize, String fontRgb,
                                       String position, int angleOfinclination) {
        for (String filepath : pdfFilePath.split(",")) {
            try {
                addWaterMark(filepath, watermark, fontSize, fontRgb, position, angleOfinclination);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    }

    private static void addWaterMark(String pdfFilePath, String watermark, float fontSize, String fontRgb,
                                     String position, int angleOfinclination)
            throws IOException, DocumentException {
        String tempfilepath = pdfFilePath + ".tmp";
        File tempFile = new File(tempfilepath);
        PdfReader reader = new PdfReader(pdfFilePath);// 待加水印的文件
        PdfStamper stamper = new PdfStamper(reader,
                new FileOutputStream(tempFile));
        int total = reader.getNumberOfPages() + 1;
        PdfContentByte content;
        BaseFont font = BASE_FONT_CHINESE;//默认字体
        //int textWidth = 200;
        //int textHeight = 50;
        String[] colArr = fontRgb.replaceAll("[ \r\n]", "").split(",");
        String[] posArr = position.replaceAll("[ \r\n]", "").split(",");
        int textWidth = Integer.parseInt(posArr[0]);
        int textHeight = Integer.parseInt(posArr[1]);
        BaseColor color = new BaseColor(Integer.parseInt(colArr[0]), Integer.parseInt(colArr[1]),
                Integer.parseInt(colArr[2]));
        for (int i = 1; i < total; i++)//循环对每页插入水印
        {
            content = stamper.getUnderContent(i);//水印的起始
            content.beginText();//开始
            content.setColorFill(color);//设置颜色
            content.setFontAndSize(font, fontSize);//设置字体及字号38
            content.setTextMatrix(textWidth, textHeight);//设置起始位置
            content.showTextAligned(Element.ALIGN_LEFT, watermark, textWidth, textHeight, angleOfinclination);//开始写入水印
            content.endText();
        }
        stamper.close();
        reader.close();
        File destFile = new File(pdfFilePath);
        destFile.delete();
        tempFile.renameTo(destFile);
    }

    private static void doAddPicMark(String pdfFilePath, String imgfilepath, String position, String big) {

        for (String filepath : pdfFilePath.split(",")) {
            try {
                addPicMark(filepath, imgfilepath, position, big);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    }

    private static void addPicMark(String pdfFilePath, String imgfilepath, String position, String big)
            throws IOException, DocumentException {
        String tempfilepath = pdfFilePath + ".tmp";
        File tempFile = new File(tempfilepath);
        PdfReader reader = new PdfReader(pdfFilePath);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(tempfilepath));
        int total = reader.getNumberOfPages() + 1;
        String[] pArr = position.replaceAll("[ \r\n]", "").split(",");
        String[] bArr = big.replaceAll("[ \r\n]", "").split(",");
        int p1 = Integer.parseInt(pArr[0]);
        int p2 = Integer.parseInt(pArr[1]);
        int b1 =Integer.parseInt(bArr[0]);
        int b2 = Integer.parseInt(pArr[1]);
        Image image = Image.getInstance(imgfilepath);
        // 图片位置
        image.setAbsolutePosition(p1, p2);
        PdfContentByte content;
        for (int i = 1; i < total; i++)//循环对每页插入水印
        {
            content = stamper.getUnderContent(i);//水印的起始
            // 添加水印图片
            content.addImage(image);
//            // 画个圈
//            content.ellipse(250, 450, 350, 550);
//            content.setLineWidth(1f);
//            content.stroke();
        }
        stamper.close();
        reader.close();
        File destFile = new File(pdfFilePath);
        destFile.delete();
        tempFile.renameTo(destFile);
    }

    private static void addFontByExcel(Row row, PdfPCell pdfpCell, Cell cell) {
        Font cellfont = getFontByExcel(cell);
        Phrase phrase = new Phrase(cell.getStringCellValue(), cellfont);
        pdfpCell.setPhrase(phrase);
        pdfpCell.setFixedHeight(row.getHeightInPoints() * 0.95f);//实际生成的高度比excel中要高
        Workbook wb = cell.getSheet().getWorkbook();
        short index = cell.getCellStyle().getFontIndex();
        org.apache.poi.ss.usermodel.Font font = wb.getFontAt(index);
        //实际生成的pdf字体比excel中要大，并且大字体会偏下，真是奇怪了的
        pdfpCell.setPaddingTop(0f);//这步不设置，有些字体会不显示 todo 啥原因？
        if(font.getFontHeightInPoints() >= 14) {
            cellfont.setSize(font.getFontHeightInPoints() - 2.2f);
        }
        else if(font.getFontHeightInPoints() >= 10) {
            cellfont.setSize(font.getFontHeightInPoints() - 1.6f);
        }
        else if(font.getFontHeightInPoints() >= 8) {
            cellfont.setSize(font.getFontHeightInPoints() - 1);
        }
        else  {
            cellfont.setSize(font.getFontHeightInPoints());
        }
    }

    private static void addBorderByExcel(PdfPCell pCell, Cell cell) {
        Workbook wb = cell.getSheet().getWorkbook();
        CellStyle style = cell.getCellStyle();
        int leftBC = getBorderRBG(wb, style.getLeftBorderColor());
        int rightBC = getBorderRBG(wb, style.getRightBorderColor());
        int topBC = getBorderRBG(wb, style.getTopBorderColor());
        int bottomBC = getBorderRBG(wb, style.getBottomBorderColor());
        if (leftBC == 0 && rightBC == 0 && topBC == 0 && bottomBC == 0) {
            //pCell.setBorder(PdfPCell.NO_BORDER);
        } else {
            leftBC = leftBC == 0 ? 16777215 : leftBC;
            rightBC = rightBC == 0 ? 16777215 : rightBC;
            topBC = topBC == 0 ? 16777215 : topBC;
            bottomBC = bottomBC == 0 ? 16777215 : bottomBC;
        }
        pCell.setBorderColorLeft(new BaseColor(leftBC));
        pCell.setBorderColorRight(new BaseColor(rightBC));
        pCell.setBorderColorTop(new BaseColor(topBC));
        pCell.setBorderColorBottom(new BaseColor(bottomBC));
    }

    protected static void addImageByPOICell(PdfPCell pdfpCell, Cell cell, float cellWidth)
            throws BadElementException, MalformedURLException, IOException {
        byte[] bytes = null;
//        PictureData pData = cell.getSheet().getWorkbook().getAllPictures().get(cell.getColumnIndex());
//        bytes = pData.getData();
        if (bytes != null) {
            //           double cw = cellWidth;
            //           double ch = pdfpCell.getFixedHeight();
            //
            //           double iw = poiImage.getDimension().getWidth();
            //           double ih = poiImage.getDimension().getHeight();
            //
            //           double scale = cw / ch;
            //
            //           double nw = iw * scale;
            //           double nh = ih - (iw - nw);
            //
            //           POIUtil.scale(bytes , nw  , nh);
            pdfpCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            pdfpCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            Image image = Image.getInstance(bytes);
            pdfpCell.setImage(image);
        }
    }

    public static int getBorderRBG(Workbook wb, short index) {
        int result = 0;

        if (wb instanceof HSSFWorkbook) {
            HSSFWorkbook hwb = (HSSFWorkbook) wb;
            HSSFColor color = hwb.getCustomPalette().getColor(index);
            if (color != null) {
                result = getRGB(color);
            }
        }

        if (wb instanceof XSSFWorkbook) {
            XSSFColor color = new XSSFColor();
            color.setIndexed(index);
            result = getRGB(color);
        }

        return result;
    }

    private static int getPOIColumnWidth(Cell cell) {
        int poiCWidth = cell.getSheet().getColumnWidth(cell.getColumnIndex());
        int colWidthpoi = poiCWidth;
        int widthPixel = 0;
        if (colWidthpoi >= 416) {
            widthPixel = (int) (((colWidthpoi - 416.0) / 256.0) * 8.0 + 13.0 + 0.5);
        } else {
            widthPixel = (int) (colWidthpoi / 416.0 * 13.0 + 0.5);
        }
        return widthPixel;
    }

    private static float getPixelHeight(float poiHeight) {
        float pixel = poiHeight / 28.6f * 26f;
        return pixel;
    }

    private static boolean isUsed(Cell cell, int rowIndex, int colIndex) {
        boolean result = false;
        Sheet sheet = cell.getSheet();
        int num = sheet.getNumMergedRegions();
        for (int i = 0; i < num; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            if (firstRow < rowIndex && lastRow >= rowIndex) {
                if (firstColumn <= colIndex && lastColumn >= colIndex) {
                    result = true;
                }
            }
        }
        return result;
    }

    private static CellRangeAddress getColspanRowspanByExcel(Cell cell, int rowIndex, int columnIndex) {
        CellRangeAddress result = null;
        Sheet sheet = cell.getSheet();
        int num = sheet.getNumMergedRegions();
        for (int i = 0; i < num; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            if (range.getFirstRow() == rowIndex && range.getFirstColumn() == columnIndex) {
                result = range;
            }
        }
        return result;
    }

    private static int getBackgroundColorByExcel(CellStyle style) {
        Color color = style.getFillForegroundColorColor();
        return getRGB(color);
    }

    private static int getVAlignByExcel(short align) {
        int result = 0;
        if (align == CellStyle.VERTICAL_BOTTOM) {
            result = Element.ALIGN_BOTTOM;
        }
        if (align == CellStyle.VERTICAL_CENTER) {
            result = Element.ALIGN_MIDDLE;
        }
        if (align == CellStyle.VERTICAL_JUSTIFY) {
            result = Element.ALIGN_JUSTIFIED;
        }
        if (align == CellStyle.VERTICAL_TOP) {
            result = Element.ALIGN_TOP;
        }
        return result;
    }

    private static int getHAlignByExcel(short align) {
        int result = 0;
        if (align == CellStyle.ALIGN_LEFT) {
            result = Element.ALIGN_LEFT;
        }
        if (align == CellStyle.ALIGN_RIGHT) {
            result = Element.ALIGN_RIGHT;
        }
        if (align == CellStyle.ALIGN_JUSTIFY) {
            result = Element.ALIGN_JUSTIFIED;
        }
        if (align == CellStyle.ALIGN_CENTER) {
            result = Element.ALIGN_CENTER;
        }
        return result;
    }

    private static Font getFontByExcel(Cell cell) {
        Font result = new Font(BASE_FONT_CHINESE, 8, Font.NORMAL);
        Workbook wb = cell.getSheet().getWorkbook();
        short index = cell.getCellStyle().getFontIndex();
        org.apache.poi.ss.usermodel.Font font = wb.getFontAt(index);
        if (font.getBoldweight() == org.apache.poi.ss.usermodel.Font.BOLDWEIGHT_BOLD) {
            result.setStyle(Font.BOLD);
        }
        if(font.getItalic()) {
            result.setStyle(Font.ITALIC);
        }
        //下划线
        FontUnderline underline = FontUnderline.valueOf(font.getUnderline());
        if (underline == FontUnderline.SINGLE) {
            String ulString = Font.FontStyle.UNDERLINE.getValue();
            result.setStyle(ulString);
        }
        return result;
    }

    protected static Font getFontByExcel(Cell cell, CellStyle style) {
        Font result = new Font(BASE_FONT_CHINESE, 8, Font.NORMAL);
        Workbook wb = cell.getSheet().getWorkbook();
        //字体样式索引
        short index = style.getFontIndex();
        org.apache.poi.ss.usermodel.Font font = wb.getFontAt(index);
        //字体颜色
        int colorIndex = font.getColor();
        if (font.getBoldweight() == org.apache.poi.ss.usermodel.Font.BOLDWEIGHT_BOLD) {
            result.setStyle(Font.BOLD);
        }
        HSSFColor color = (HSSFColor) HSSFColor.getIndexHash().get(colorIndex);
        if (color != null) {
            int rbg = getRGB(color);
            result.setColor(new BaseColor(rbg));
        }
        //下划线
        FontUnderline underline = FontUnderline.valueOf(font.getUnderline());
        if (underline == FontUnderline.SINGLE) {
            String ulString = Font.FontStyle.UNDERLINE.getValue();
            result.setStyle(ulString);
        }
        return result;
    }

    public static int getRGB(Color color) {
        int result = 0x00FFFFFF;

        int red = 0;
        int green = 0;
        int blue = 0;

        if (color instanceof HSSFColor) {
            HSSFColor hssfColor = (HSSFColor) color;
            short[] rgb = hssfColor.getTriplet();
            red = rgb[0];
            green = rgb[1];
            blue = rgb[2];
        }

        if (color instanceof XSSFColor) {
            XSSFColor xssfColor = (XSSFColor) color;
            byte[] rgb = xssfColor.getRgb();
            red = (rgb[0] < 0) ? (rgb[0] + 256) : rgb[0];
            green = (rgb[1] < 0) ? (rgb[1] + 256) : rgb[1];
            blue = (rgb[2] < 0) ? (rgb[2] + 256) : rgb[2];
        }

        if (red != 0 || green != 0 || blue != 0) {
            result = new java.awt.Color(red, green, blue).getRGB();
        }
        return result;
    }

    protected static BaseFont BASE_FONT_CHINESE;

    static {
        try {
            BASE_FONT_CHINESE = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
//            BASE_FONT_CHINESE = BaseFont.createFont("C:/windows/fonts/simsun.ttc,1",
//                    BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//            BASE_FONT_CHINESE = BaseFont.createFont("STSong-Light",
//                    "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 使用系统字体
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

